from game.object.world.world import *
from game.server.server_main import *
from pygame.locals import *

#Resolution levels
#0 = 1000km
#1 = 100km
#2 = 10km
#3 = 1km
#4 = 100m
#5 = 10m
#6 = 1m
#7 = 10cm
#8 = 1cm (object positioning only)

#The largest block loaded
HEIGHTEST_LEVEL = 2
#The how many blocks in any direction to load at said blocks internal unit size
VIEW_DISTANCE = 2;

class ClientModel:
    def __init__(self, client):
        self.coord = [5,1,5, #1000km
                      5,1,5, #100km
                      5,1,5, #10km
                      0,0,0, #1km
                      5,0,0, #100m
                      5,1,1, #10m
                      5,1,0] #1m
        self.roots = [None]*9
        self.client = client
        self.server = Server()
        self.first = 0

    def first_load(self):
        """
        When the game is first loaded ask the server where we actually are
        """

        #load root nodes
        for d in xrange(7):
            self.load(self.coord, d, 0)

        for d in xrange(HEIGHTEST_LEVEL,6+1):
            tempCoord = self.coord[:]
            di = d*3;
            for x in xrange(-VIEW_DISTANCE,VIEW_DISTANCE+1):
                tempCoord[di] = self.coord[di]+x
                for y in xrange(-VIEW_DISTANCE,VIEW_DISTANCE+1):
                    tempCoord[di+1] = self.coord[di+1]+y
                    for z in xrange(-VIEW_DISTANCE,VIEW_DISTANCE+1):
                        tempCoord[di+2] = self.coord[di+2]+z
                        self.load(tempCoord, d, 1)

    def load(self, coord, coord_depth, lod):
        """
        Send a request to the server to load one block at the given level
        """
        self.server.load_block(self.normalise_coord(coord,coord_depth), coord_depth,lod,self)

    def add_block(self, coord, coord_depth, newBlock):
        """
        This function is called when the server has loaded a new block and it has
        been sent to the client. The coord variable tells the client model where
        this block needs to be inserted into the clients current scene
        """


        if(coord_depth == 0):
            self.roots[0] = newBlock
            return
        if(coord_depth == 1):
            self.roots[0].add_child(newBlock)
            self.roots[coord_depth] = newBlock
            return
        
        if(self.roots[coord_depth-1] is None): # At this point we can only add a block if we have a parent block already loaded
            #print "dropped block ", coord, ", depth:", coord_depth, ", pp:", self.coord
            return


        if(self.is_root(coord, coord_depth)):# and self.roots[coord_depth] is None):
            #print "adding root block ", coord[0:coord_depth*3+3], ", depth:", coord_depth, ", pp:", self.coord
            #self.roots[coord_depth-1].add_child(newBlock)
            self.roots[coord_depth] = newBlock
            #return

        d3 = (coord_depth)*3
        #print "adding block ", coord[d3],coord[d3+1],coord[d3+2], " at ", coord[0:d3+3]
        #self.roots[coord_depth-2].get_block(coord[d3-3],coord[d3-2],coord[d3-1]).set_block(coord[d3],coord[d3+1],coord[d3+2],newBlock)
        self.get_cell(coord,coord_depth-1).set_block(coord[d3],coord[d3+1],coord[d3+2],newBlock)
        #print "added block  ", newBlock.x , newBlock.y, newBlock.z, " at ", coord[d3:d3+3]
#        print "c:",newBlock.count

    def get_cell(self,coord,coord_depth):
        cd = coord_depth;
        while( not self.is_root(coord, cd) ):
            cd-=1

        cell = self.roots[cd]
        while(cd < coord_depth):
            cd+=1
            cell = cell.get_block(coord[cd*3],coord[cd*3+1],coord[cd*3+2])
            

        
        return cell

    def is_root(self, coord, coord_depth):
        return coord[0:coord_depth*3+3] == self.coord[0:coord_depth*3+3]


    def normalise_coord(self, coord, coord_depth):
        """
        Because alot of this code it dodgy some coordinates are dodgy... there
        are no negatives in this coordinate systems so this method makes a coord
        that contains some negative and does some more dodgy stuff to it.
        """

#        if(self.first < 30):
#            print coord
        #    print reversed( xrange(coord_depth+1,0))
        coord = coord[:]
        for d in reversed( xrange(0,coord_depth+1)):
#            if(self.first == 4):
#                print "foo: ", d, ",",coord_depth
            d3 = d*3
            for i in xrange(3):
#                if(self.first == 4):
#                    print "d:", coord[d3+i], ",d-3:",coord[d3+i-3]
                if(coord[d3+i] > 9):
                    coord[d3+i-3] += coord[d3+i] // 10
                    coord[d3+i] = coord[d3+i] % 10
                elif(coord[d3+i] < 0):
                    coord[d3+i-3] -= (-coord[d3+i] // 10) + 1
                    coord[d3+i] = 10 - (-coord[d3+i] % 10)

#        if(self.first < 30):
#            print coord

        self.first += 1

        return coord

    def input_hook(self, event, ms):
        if(event.type == KEYUP and event.key == K_KP1):
            self.shift_model(6,WORLD_YN)
        if(event.type == KEYUP and event.key == K_KP7):
            self.shift_model(6,WORLD_YP)
        if(event.type == KEYUP and event.key == K_KP2):
            self.shift_model(6,WORLD_ZN)
        if(event.type == KEYUP and event.key == K_KP8):
            self.shift_model(6,WORLD_ZP)
        if(event.type == KEYUP and event.key == K_KP4):
            self.shift_model(6,WORLD_XN)
        if(event.type == KEYUP and event.key == K_KP6):
            self.shift_model(6,WORLD_XP)

    def shift_model(self, coord_depth, direction):
        new_coord = self.coord[:]

        di = coord_depth*3;
        new_coord[di] = new_coord[di] + WORLD_X[direction]
        new_coord[di+1] = new_coord[di+1] + WORLD_Y[direction]
        new_coord[di+2] = new_coord[di+2] + WORLD_Z[direction]
        new_coord = self.normalise_coord(new_coord,coord_depth)

        tempCoord = new_coord[:]

        

        if(direction == WORLD_XN or direction == WORLD_XP):
            tempCoord = self.coord[:]
            di = coord_depth*3;
            tempCoord[di] = tempCoord[di]+WORLD_X[direction]*VIEW_DISTANCE
            
            for y in xrange(-VIEW_DISTANCE,VIEW_DISTANCE+1):
                tempCoord[di+1] = self.coord[di+1]+y
                for z in xrange(-VIEW_DISTANCE,VIEW_DISTANCE+1):
                    tempCoord[di+2] = self.coord[di+2]+z
                    self.load(tempCoord,coord_depth, 0)

        self.coord = new_coord

        print "RAWR"

        #self.load(coord, coord_depth, 1)
        #self.first_load()
